/**
 * COPYRIGHT HangZhou Trustway Technology Company Limited
 * All right reserved.
 */
package com.robam.cloud.database.register;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.robam.cloud.database.config.DataSourceConfiguration;
import com.robam.cloud.database.datasource.DynamicDataSource;
import com.robam.cloud.database.util.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;

import javax.sql.DataSource;
import java.util.Map;
import java.util.Properties;

/**
 * @Description
 * @Author 薛铁琪
 * @CreateTime 2020/7/5 15:12
 * @Version 1.0
 */
@Slf4j
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    DynamicDataSource dynamicDataSource;

    @Override
    public void setEnvironment(Environment environment) {
        Map<String, DataSourceConfiguration> propMap = Binder.get(environment)
                .bind("robam.component.database.dblist", Bindable.mapOf(String.class, DataSourceConfiguration.class)).get();
        dynamicDataSource = new DynamicDataSource();
        for (Map.Entry<String, DataSourceConfiguration> entry : propMap.entrySet()) {
            String mapKey = entry.getKey();
            DataSourceConfiguration mapValue = entry.getValue();
            DataSource dataSource = buildDataSource(mapValue);
            log.debug("component-databaselog-----------{}数据源配置完成", mapKey);
            if (DynamicDataSourceContextHolder.DEFAULT_SOURCE.equals(mapKey)) {
                dynamicDataSource.setDefaultTargetDataSource(dataSource);
                dynamicDataSource.addTargetDataSource(mapKey, dataSource);
            } else {
                dynamicDataSource.addTargetDataSource(mapKey, dataSource);
            }
        }
    }


    public DataSource buildDataSource(DataSourceConfiguration dataSourceConfigurationHashMap) {
        Properties dbProperties = new Properties();
        dbProperties.put("url", dataSourceConfigurationHashMap.getUrl());
        dbProperties.put("username", dataSourceConfigurationHashMap.getUsername());
        dbProperties.put("password", dataSourceConfigurationHashMap.getPassword());
        dbProperties.put("driverClassName", dataSourceConfigurationHashMap.getDriverClassName());
        dbProperties.put("initialSize", dataSourceConfigurationHashMap.getInitialSize());
        dbProperties.put("maxActive", dataSourceConfigurationHashMap.getMaxActive());
        dbProperties.put("minIdle", dataSourceConfigurationHashMap.getMinIdle());
        dbProperties.put("maxIdle", dataSourceConfigurationHashMap.getMaxIdle());
        dbProperties.put("maxWait", dataSourceConfigurationHashMap.getMaxWait());
        dbProperties.put("validationQuery", dataSourceConfigurationHashMap.getValidationQuery());
        dbProperties.put("testOnBorrow", dataSourceConfigurationHashMap.getTestOnBorrow());
        dbProperties.put("testOnReturn", dataSourceConfigurationHashMap.getTestOnReturn());
        dbProperties.put("testWhileIdle", dataSourceConfigurationHashMap.getTestWhileIdle());
        dbProperties.put("timeBetweenEvictionRunsMillis", dataSourceConfigurationHashMap.getTimeBetweenEvictionRunsMillis());
        dbProperties.put("minEvictableIdleTimeMillis", dataSourceConfigurationHashMap.getMinEvictableIdleTimeMillis());
        dbProperties.put("removeAbandoned", dataSourceConfigurationHashMap.getRemoveAbandoned());
        dbProperties.put("removeAbandonedTimeout", dataSourceConfigurationHashMap.getRemoveAbandonedTimeout());
        dbProperties.put("logAbandoned", dataSourceConfigurationHashMap.getLogAbandoned());
        try {
            dbProperties.put("filters", dataSourceConfigurationHashMap.getFilters());
            dbProperties.put("connectionProperties", dataSourceConfigurationHashMap.getConnectionProperties());
            DataSource dataSource = DruidDataSourceFactory.createDataSource(dbProperties);
            return dataSource;
        } catch (Exception var4) {
            var4.printStackTrace();
            return null;
        }
    }


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(DynamicDataSource.class);
        beanDefinition.setSynthetic(true);
        beanDefinition.setPrimary(true);
        MutablePropertyValues mpv = beanDefinition.getPropertyValues();
        mpv.addPropertyValue("defaultTargetDataSource", dynamicDataSource.getDefaultTargetDataSource());
        mpv.addPropertyValue("targetDataSources", dynamicDataSource.getTargetDataSources());
        log.debug("component-databaselog-----------dynamicDataSource工厂注册");
        registry.registerBeanDefinition("dynamicDataSource", beanDefinition);
    }

}
